package com.sn.author.domain;

import com.alibaba.fastjson.JSON;
import com.sn.author.common.enums.ExceptionEnum;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import java.io.Serializable;

/**
 * @Author Xiaoming
 * @Date 2019/9/11 14:58
 * @Version 1.0.0
 **/
@Data
@EqualsAndHashCode
@AllArgsConstructor
public class BaseResult<T> implements Serializable {

    /**
     * Response message.
     */
    private String message;
    /**
     * Response status
     */
    private Integer code;
    /**
     * Response data
     */
    private T data;
    /**
     * Response total time
     */
    private Long responseTime = System.currentTimeMillis();
    /**
     * If log level is debug. Server throw exception detail info write to devMessage.
     */
    private String devMessage;
    /**
     * total
     */
    private Long total;

    public BaseResult() {
    }

    /**
     * Create response status and message.
     * @param code  response status
     * @param message response message
     * @return success result with status and message.
     */
    public BaseResult(@NonNull Integer code, @Nullable String message) {
        this.code = code;
        this.message = message;
    }

    /**
     * Create response message.with status,message and responseData.
     * @param code    Res status
     * @param message   Res message
     * @param data   Res data
     * @return success result with status,message and data.
     */
    public BaseResult(@NonNull Integer code, @Nullable String message, @Nullable T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    /**
     * Create response body with custom enum class.
     * @param exceptionEnum  custom enum.
     */
    public BaseResult(@NonNull ExceptionEnum exceptionEnum){
        this.message = exceptionEnum.getMessage();
        this.code = exceptionEnum.getCode();
    }

    /**
     * Create response body wth data.
     * @param data  Response data (Default response status is 200 and message is "OK").
     * @return Default success result.
     */
    public BaseResult(@NonNull T data) {
        this.code = ExceptionEnum.SUCCESS.getCode();
        this.message = ExceptionEnum.SUCCESS.getMessage();
        this.data = data;
    }

    /**
     * Create response body with data and total.
     * @param rspBody  Response data
     * @param total    Response data's total number
     * @param <T>      Data type
     * @return Success result body with data and total (Default status is 200 and message is OK)
     */
    public static <T> BaseResult<T> success(@NonNull T rspBody, Long total){
        BaseResult<T> result = new BaseResult<>();
        result.setCode(ExceptionEnum.SUCCESS.getCode());
        result.setMessage(ExceptionEnum.SUCCESS.getMessage());
        result.setData(rspBody);
        result.setTotal(total);
        return result;
    }

    /**
     * Create response body with data
     * @param rspBody Response data
     * @param <T>     Data type
     * @return Success result body.Default
     */
    public static <T> BaseResult<T> success(@Nullable T rspBody){
        BaseResult<T> result = new BaseResult<>();
        result.setCode(ExceptionEnum.SUCCESS.getCode());
        result.setMessage(ExceptionEnum.SUCCESS.getMessage());
        result.setData(rspBody);
        return result;
    }


    /**
     * Create exception response body with error info
     * @param code    Response status
     * @param message Response message
     * @return Error info body
     */
    public static <T> BaseResult<T> makeExceptionResult(@NonNull Integer code, String message){
        BaseResult<T> result = new BaseResult<>();
        result.setCode(code);
        result.setMessage(message);
        return result;
    }

    /**
     * Create exception response body with errro info (Default status code is 500)
     * @param message   error info message
     * @return Error info body
     */
    public static <T> BaseResult<T> makeExceptionResult(String message){
        BaseResult<T> result = new BaseResult<>();
        result.setCode(ExceptionEnum.UNKNOWN_ERR.getCode());
        result.setMessage(message);
        return result;
    }

    public String toJson(){
        return JSON.toJSONString(this);
    }
}
